package org.jf.aab;

import net.dongliu.apk.parser.bean.ApkSigner;
import net.dongliu.apk.parser.bean.CertificateMeta;
import net.dongliu.apk.parser.parser.CertificateParser;
import net.dongliu.apk.parser.utils.Inputs;
import org.jf.aab.entry.AabMeta;
import org.jf.aab.entry.CertificateFile;

import java.io.File;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/*
 * zhulei 2024/8/7-上午9:58
 */
public class AabFile {

    private final ZipFile zf;
    private File aabFile;

    private String manifestXml;
    private AabMeta aabMeta;
    private List<ApkSigner> apkSigners;

    private boolean manifestParsed;

    public AabFile(File aabFile) throws IOException {
        this.aabFile = aabFile;
        this.zf = new ZipFile(aabFile);
    }

    public AabFile(String aabPath) throws IOException {
        this(new File(aabPath));
    }

    /**
     * return decoded AndroidManifest.xml
     *
     * @return decoded AndroidManifest.xml
     */
    public AabMeta getAabMeta() throws IOException {
        parseManifest();
        return this.aabMeta;
    }

    private void parseManifest() throws IOException {
        if (manifestParsed) {
            return;
        }
        aabMeta = ApkMetaTranslator.INSTANCE.parse(aabFile);
        manifestParsed = true;
    }

    protected List<CertificateFile> getAllCertificateData() throws CertificateException, IOException {
        Enumeration<? extends ZipEntry> enu = zf.entries();
        List<CertificateFile> list = new ArrayList<>();
        while (enu.hasMoreElements()) {
            ZipEntry ne = enu.nextElement();
            if (ne.isDirectory()) {
                continue;
            }
            String name = ne.getName().toUpperCase();
            if (name.endsWith(".RSA") || name.endsWith(".DSA")) {
                list.add(new CertificateFile(name, Inputs.readAllAndClose(zf.getInputStream(ne))));
            }
        }
        return list;
    }

    public List<ApkSigner> getApkSingers() throws IOException, CertificateException {
        if (apkSigners == null) {
            parseCertificates();
        }
        return this.apkSigners;
    }

    private void parseCertificates() throws IOException, CertificateException {
        this.apkSigners = new ArrayList<>();
        for (CertificateFile file : getAllCertificateData()) {
            CertificateParser parser = CertificateParser.getInstance(file.getData());
            List<CertificateMeta> certificateMetas = parser.parse();
            apkSigners.add(new ApkSigner(file.getPath(), certificateMetas));
        }
    }

}
